﻿/*
 * spinlock.cpp
 *
 *  Created on: 2018年3月20日
 *      Author: Dylan.Gao
 */

#include <dm/export.hpp>

#define DM_API_OS_COMMON DM_API_EXPORT

#include <dm/os/spinlock.hpp>
#include <cstdlib>

#ifdef WIN32
#include <Windows.h>
#else
#include <pthread.h>
#include <sched.h>
#endif

namespace dm{
namespace os{

static const unsigned int Locked = 1u;
static const unsigned int Unlock = 0u;

CSpinlock::CSpinlock(){
#ifndef WIN32
	__sync_fetch_and_and(&m_state,Unlock);
#else
	InterlockedExchange(&m_state, Unlock);
#endif
}

bool CSpinlock::tryLock( dm::uint64 times ){
	if( times==0 )
		return m_state==Unlock;

	for( volatile dm::uint64 i=0;i<times;++i ){
		// 如果锁之前是未锁，说明成功，否则失败
#ifndef WIN32
		if (Unlock == __sync_fetch_and_or(&m_state, Locked))
			return true;
		sched_yield();
#else
		if (Unlock == InterlockedExchange(&m_state, Locked))
			return true;
		SwitchToThread();
#endif		
	}

	return false;
}

void CSpinlock::lock( dm::uint64 times ){
	if( times==0 ){
#ifndef WIN32
		while( __sync_fetch_and_or(&m_state,Locked)==Unlock )
			break;
#else
		while (InterlockedExchange(&m_state, Locked) == Unlock)
			break;
#endif
	}else{
		for( volatile dm::uint64 i=0;i<times;++i ){
#ifndef WIN32
			if( __sync_fetch_and_or(&m_state,Locked)==Unlock )
				break;
			sched_yield();
#else
			if (InterlockedExchange(&m_state, Locked) == Unlock)
				break;
			SwitchToThread();
#endif
		}

		// 当前肯定是锁定了，但非本函数锁定的
	}
}

void CSpinlock::unlock(){
#ifndef WIN32
	__sync_fetch_and_and(&m_state,Unlock);
#else
	InterlockedExchange(&m_state, Unlock);
#endif
}

}
}


